/*
 *  attribute_info.h
 *
 *  Copyright (C) 2011  Jason<linux8192@gmail.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _ATTRIBUTE_INFO_H_
#define _ATTRIBUTE_INFO_H_

#include "type.h"
#include "constant_info.h"

/*
 * Misc attribute definations
 */
#define ATTRIBUTE_CODE				0
#define ATTRIBUTE_CONSTANT_VALUE		1
#define ATTRIBUTE_DEPRECATED			2
#define ATTRIBUTE_EXCEPTION			3
#define ATTRIBUTE_INNER_CLASSES			4
#define ATTRIBUTE_LINE_NUMBER_TABLE		5
#define ATTRIBUTE_LOCAL_VARIABLE_TABLE		6
#define ATTRIBUTE_SOURCE_FILE			7
#define ATTRIBUTE_SYNTHETIC			8

/*
 * The base attribute pool info as the "super class",
 * should be placed at the beginning of "devided classes".
 */
typedef struct _attribute_info {
	u2	attribute_name_index;
	u4	attribute_length;
} attr_t;

#define __parse_attribute_base(_base_obj, _buff_cur)		\
do {								\
	(_base_obj).attribute_name_index = read_u2(_buff_cur);	\
	(_buff_cur) += 2;					\
	(_base_obj).attribute_length = read_u4(_buff_cur);	\
	(_buff_cur) += 4;					\
} while (0)

typedef struct _exception_table {
	u2	start_pc;
	u2	end_pc;
	u2	handler_pc;
	u2	catch_type;
} exception_table_t;


/* Some fields' offset or size in class file (NOT STRUCT) */
#define CODE_ATTR_CODE_LENGTH_OFFSET	10
#define CODE_ATTR_EXP_TABLE_SIZE	8

typedef struct _code_attribute {
	attr_t			base;

	u2			max_stack;
	u2			max_locals;

	u4			code_length;
	char			*code;

	u2			exception_table_length;	
	exception_table_t	*exception_table;

	u2			attributes_count;
	attr_t			**attributes;

} code_attr_t;

typedef struct _constant_value_attribute {
	attr_t			base;
	u2			constant_value_index;
} constant_value_attr_t;

typedef struct _deprecated_attribute {
	attr_t			base;
} deprecated_attr_t;

typedef struct _exception_attribute {
	attr_t			base;
	u2			number_of_exceptions;
	u2			exception_index_table[0];
} exception_attr_t;

#define INNER_CLASS_INFO_SIZE		8
typedef struct _inner_class_info {
	u2			inner_class_info_index;
	u2			outer_class_info_index;
	u2			inner_name_index;

#define INNER_CLASS_FLAG_ACC_PUBLIC	0x0001
#define INNER_CLASS_FLAG_ACC_PRIVATE	0x0002
#define INNER_CLASS_FLAG_ACC_PROTECTED	0x0004
#define INNER_CLASS_FLAG_ACC_STATIC	0x0008
#define INNER_CLASS_FLAG_ACC_FINAL	0x0010
#define INNER_CLASS_FLAG_ACC_INTERFACE	0x0200
#define INNER_CLASS_FLAG_ACC_ABSTRACT	0x0400

	u2			inner_class_access_flags;
} inner_class_info_t;

typedef struct _inner_classes_attribute {
	attr_t			base;
	u2			number_of_classes;
	inner_class_info_t	classes[0];
} inner_classes_attr_t;

#define LINE_NUMBER_INFO_SIZE		4
typedef struct _line_number_info {
	u2			start_pc;
	u2			line_number;
} line_number_info_t;

typedef struct _line_number_table_attribute {
	attr_t			base;
	u2			line_number_table_length;
	line_number_info_t	line_number_table[0];
} line_number_table_attr_t;

#define LOCAL_VARIABLE_INFO_SIZE	10

typedef struct _local_variable_info {
	u2			start_pc;
	u2			length;
	u2			name_index;
	u2			descriptor_index;
	u2			index;
} local_variable_info_t;

typedef struct _local_variable_table_attribute {
	attr_t			base;
	u2			local_variable_table_length;
	local_variable_info_t	local_variable_table[0];
} local_variable_table_attr_t;

typedef struct _source_file_attribute {
	attr_t			base;
	u2			source_file_index;
} source_file_attr_t;

typedef struct _synthetic_attribute {
	attr_t			base;
} synthetic_attr_t;

int parse_attribute_pool(const char *buff, attr_t **attr_list, const int count, const cp_info_t **cp_list);

#endif /* _ATTRIBUTE_INFO_H_ */
